from contests.models import Problem, Submission, Contest
from django.contrib.auth.models import User
from django import forms
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_GET
from django.core.context_processors import csrf
from django.template import RequestContext
from datetime import datetime
import os
import commands
import random
########## TO-DO: get logging working ##########
import logging
LOG_FILENAME = 'logs/testing.log'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
################################################

## Handle the request when the user goes to /contestron
# HOMEPAGE
#@login_required
def base(request):
    # grab the current user
    if request.user.is_authenticated():
        current_user = str(request.user.username).split('@')[0]
    else:
        current_user = "NOT LOGGED IN"
        
    return render_to_response('home.html',
                              {'current_user': current_user},
                              context_instance=RequestContext(request))

## Handle the request when the user goes to /contestron/problems
# PROBLEMS PAGE
#@login_required
def problems(request):
    current_user = request.user.username
    problems_list = Problem.objects.order_by('start_time')

    # variables for the template
    page_vars = {'problems_list': problems_list,
                 'current_user': current_user}


    # Post will be if the user submitted a file
    if request.method == 'POST':
#        form = UploadFileForm(request.POST, request.FILES)
#        if form.is_valid():
        prob_name = request.POST['probname']

        # This if-statement prevents students from using an old page to submit a solution
        # after the problem has already closed, UNLESS it is in overtime
        curr_prob = Problem.objects.get(name=prob_name)
        if curr_prob.status() == "overtime" or datetime.now() < curr_prob.close_time :
            page_vars['upload'] = handle_uploaded_file(request.FILES['file'],current_user,prob_name)
            page_vars['upload_in_time'] = True
        else:
            page_vars['upload_in_time'] = False

        # Extra vars if a user just uploaded a file
        page_vars['postdata'] = request.POST
        page_vars['pname'] = request.POST['probname']

        return render_to_response('problems.html',page_vars,context_instance=RequestContext(request))
#        else:
            # let the user know the form is not valid
#            return render_to_response('problems.html',{'problems_list': problems_list, 'current_user': 'UPLOAD NOT VALID', 'upload':True, 'postdata':request.POST},context_instance=RequestContext(request))
    #else:
     #   form = UploadFileForm()        

    
    
    # User did not submit file, show upload box according to whether the user already submitted and problem is in overtime
    return render_to_response('problems.html',page_vars,context_instance=RequestContext(request))


###########################
##  File Upload Helpers  ##
###########################

# This class allows validation on the form.
# Note, this does not create the html for the form,
# its simply for validating a form that is in the 
# problems.html template
class UploadFileForm(forms.Form):
    file  = forms.FileField()

# Takes a file, the username of the person who submitted the file,
# and the problem name, and writes the file into the submissions directory,
# and then grades it.
# Args: f=file, u=username, p=problem-name
# Returns True if the file was uploaded successfully, otherwise False TO-DO
def handle_uploaded_file(f,u,p):
    logging.debug('-------------------------------------- NEW UPLOAD ---------------------------------------')
    logging.debug('invoking handle_upload_file() with args: u=' + u + ', p=' + p)

    # write the file into the submissions directory
    fn = u + '-' + p + '.scm'
    path = '/home/dtdannen/Projects/contestron/contestron1/submissions/' + fn
    destination = open(path, 'wb+')
    for chunk in f.chunks():
        destination.write(chunk)
    destination.close()

    logging.debug('file was succussfully written to: ' + path)


######################################################
## MAJOR TODO !!!!!!    
## Get autograder working, right now its just random
######################################################    

# Grade the file
#    PATH=/home/dtdannen/Projects/contestron/contestron1/autograder/sgrade-scheme sg.ss %s < %s" % (p, path))
    #cmd = ("env SCHEMEHEAPDIRS=/usr/lib/csv8.1/i3le PATH=$PATH:/home/dtdannen/Projects/contestron/contestron1/autograder/sgrade-scheme sg.ss %s < %s" % (p, path))
#    cmd = "pwd"
    #logging.debug("[Autograder Invocation] " + cmd)
    #output = commands.getoutput(cmd)
    #logging.debug("[Autograder Output] " + output)

    # Need to autograde the submission here, then set the is_correct to the resulting value

    prob = Problem.objects.get(name=p) 

    # Temporary random grading
    new_rand_val = random.randint(0,1)
    if new_rand_val == 0:
        sub_correct = False
        p_score = 0
    else:
        sub_correct = True
        p_score = prob.points
    
        

    # Add this into the submissions table of the database
    user = User.objects.get(username=u)

    #logging.debug('User object with username=' + user.username + ', found successfully')

    logging.debug('User=' + user.username + ' just tried submitting a file')


     # TODO use the current contest
    curr_contest = Contest.objects.get(is_current=True)

    # TO-DO, give the user points based on what the autograder says. Right now gives them full points
    curr_sub = Submission(user=user,problem_name=prob,contest_name=curr_contest,is_correct=sub_correct,score=p_score,file_name=fn)
    curr_sub.save()
    logging.debug('File was successfully saved into submissions table')
    logging.debug('-------------------------------------- ADDED TO SUBMISSIONS TABLE ---------------------------------------')
    
    return True
###############################
##  END File Upload Helpers  ##
###############################


@login_required
@require_GET
def results(request):
    current_user = request.user.username

    first_row = ['Problem','Correct?']
    rmatrix = []

    logging.debug("----------------------- IN USER RESULTS --------------------------")

    # For all problems that are closed, add the user's submission to the table
    closed_probs = []
    for p in Problem.objects.all():
        curr_row = []
        if p.status() == "closed":
            curr_row.append(p.name)
            logging.debug("Attempt to grab submissions for user=" + current_user + ", for problem=" + str(p.name))

            try:
                s = Submission.objects.filter(user=User.objects.get(username=current_user),problem_name=p)[0]
                logging.debug("Attempt SUCCESS for user=" + current_user + ", for problem=" + str(p.name))
#                s = Submission.objects.get(user=u,problem_name=problems[i])
                if s.is_correct:
                    curr_row.append('Yes')
                else:
                    curr_row.append('No')
            except:
                curr_row.append('No Submission')

        rmatrix.append(curr_row)

    if rmatrix == []:
        msg = "No problems are closed yet, please check back soon..."
    else:
        msg = "Results are shown only for problems that have already closed"

    logging.debug("----------------------- END USER RESULTS --------------------------")

    return render_to_response('results.html',
                              {'current_user': current_user, 'msg':msg, 'header_row':first_row, 'rmatrix':rmatrix},                             
                              context_instance=RequestContext(request))    

@login_required
@require_GET
def allResults(request):
    current_user = request.user.username

    logging.debug('=================== START admin-results =======================')
    
    # If a non staff member tries to access this site, just redirect them to their results page
    if not request.user.is_staff:
        return HttpResponseRedirect('/contestron/results/')
        
    # Now that we know the user is a staff member, just get some data
    
    # TO-DO: make a nicer results page
    
    # for now just create a matrix of all the values
    rmatrix = []
    problems = Problem.objects.order_by("close_time")
    logging.debug('===== There are ' + str(len(problems)) + ' problems')
    users = User.objects.order_by("username")
    logging.debug('===== There are ' + str(len(users)) + ' users')
    num_probs = len(problems)
    
    first_row = ['USERNAME']
    for p in problems:
        first_row.append(p.name)

    logging.debug('===== Created the first row....')        

    logging_row_counter = 1

    curr_user_row = []
    for u in users:
        curr_user_row.append(u.username)
        i  = 0
        logging.debug('===== Created the ' + str(logging_row_counter) + 'ith row in rmatrix....')                
        while i < num_probs:
            try:
                s = Submission.objects.filter(user=u,problem_name=problems[i])[0] 
                curr_user_row.append(s.score)
                i+=1
            except:
                curr_user_row.append('No Submission')
                i+=1
        rmatrix.append(curr_user_row)
        curr_user_row = []
        logging_row_counter+=1

    logging.debug('===== There are ' + str(len(rmatrix)) + ' rows in rmatrix')                


    logging.debug('=================== END admin-results =======================')                
    return render_to_response('admin_results.html',
                              {'current_user': current_user, 'header_row':first_row, 'rmatrix':rmatrix},
                              context_instance=RequestContext(request))           


        
    
    
    
        
        
    
        

    
# When a user clicks submit to upload a file, they are 
# redirected here
def problem_upload(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file']) # TO-DO
            return HttpResponseRedirect('/problems/')
        else:
            form = UploadFileForm()
        return render_to_response('problems.html', {'form': form})
        
    

